package com.msmall.community.roster.service.impl;

import java.util.List;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.msmall.base.service.impl.BaseManagerImpl;
import com.msmall.base.util.ConstantDB;
import com.msmall.community.common.model.Message;
import com.msmall.community.common.service.MessageManager;
import com.msmall.community.roster.dao.RosterDao;
import com.msmall.community.roster.dao.RosterGroupDao;
import com.msmall.community.roster.model.Roster;
import com.msmall.community.roster.model.RosterGroup;
import com.msmall.community.roster.model.RosterItem;
import com.msmall.community.roster.service.RosterManager;
import com.msmall.community.user.model.UserInfo;
import com.msmall.community.user.service.UserManager;

public class RosterManagerImpl extends BaseManagerImpl<Roster, Long> implements RosterManager{
	
	private static final Log log = LogFactory.getLog(RosterManagerImpl.class);
	
	private RosterDao rosterDao;

	private RosterGroupDao rosterGroupDao;
	
	private MessageManager messageManager;
	
	private UserManager userManager;
	
	public void setRosterDao(RosterDao rosterDao) {
		this.rosterDao = rosterDao;
	}
	public void setRosterGroupDao(RosterGroupDao rosterGroupDao) {
		this.rosterGroupDao = rosterGroupDao;
	}
	public void setMessageManager(MessageManager messageManager) {
		this.messageManager = messageManager;
	}
	
	public void setUserManager(UserManager userManager) {
		this.userManager = userManager;
	}
	/**
	 * 获得用户默认陌生人组
	 * 如果没有，则创建
	 */
	public RosterGroup getGroupStranger(Long userid){
		RosterGroup group = null;
		try {
			group = rosterGroupDao.getGroup(userid, ConstantDB.ROSTER_GROUP_NAME_STRANGER);
		} catch (Exception e) {
		}
		if(group == null){
			group = new RosterGroup();
			group.setUserid(userid);
			group.setRank(ConstantDB.ROSTER_RANK_DEFAULT);
			group.setName(ConstantDB.ROSTER_GROUP_NAME_STRANGER);
			group = (RosterGroup) rosterGroupDao.saveObject(group);
		}
		return group;
	}
	/**
	 * 获得用户默认好友组
	 * 如果没有，则创建
	 */
	public RosterGroup getGroupFriend(Long userid){
		RosterGroup group = null;
		try {
			group = rosterGroupDao.getGroup(userid, ConstantDB.ROSTER_GROUP_NAME_FRIENDS);
		} catch (Exception e) {
		}
		if(group == null){
			group = new RosterGroup();
			group.setUserid(userid);
			group.setRank(ConstantDB.ROSTER_RANK_DEFAULT);
			group.setName(ConstantDB.ROSTER_GROUP_NAME_FRIENDS);
			group = (RosterGroup) rosterGroupDao.saveObject(group);
		}
		return group;
	}
	/**
	 * 获得用户默认黑名单组
	 * 如果没有，则创建
	 */
	public RosterGroup getGroupBlacklist(Long userid){
		RosterGroup group = null;
		try {
			group = rosterGroupDao.getGroup(userid, ConstantDB.ROSTER_GROUP_NAME_BLACKLIST);
		} catch (Exception e) {
		}
		if(group == null){
			group = new RosterGroup();
			group.setUserid(userid);
			group.setRank(ConstantDB.ROSTER_RANK_DEFAULT);
			group.setName(ConstantDB.ROSTER_GROUP_NAME_BLACKLIST);
			group = (RosterGroup) rosterGroupDao.saveObject(group);
		}
		return group;
	}
	/**
	 * 获得用户默认被黑名单组
	 * 如果没有，则创建
	 */
	public RosterGroup getGroupForbidden(Long userid){
		RosterGroup group = null;
		try {
			group = rosterGroupDao.getGroup(userid, ConstantDB.ROSTER_GROUP_NAME_FORBIDDEN);
		} catch (Exception e) {
		}
		if(group == null){
			group = new RosterGroup();
			group.setUserid(userid);
			group.setRank(ConstantDB.ROSTER_RANK_DEFAULT);
			group.setName(ConstantDB.ROSTER_GROUP_NAME_FORBIDDEN);
			group = (RosterGroup) rosterGroupDao.saveObject(group);
		}
		return group;
	}
	/**
	 * 创建双方的好友关系
	 */
	private void createRoster(UserInfo owner, UserInfo friend, String content) throws Exception{
		try{
			RosterGroup pubG = getGroupStranger(owner.getUserid());
			Roster pub = new Roster();
			pub.setNickname(friend.getNickname());
			pub.setStatus(ConstantDB.ROSTER_REQUEST);
			pub.setUserid(friend.getUserid());
			pub.setGroup(pubG);
			pub = (Roster)rosterDao.saveObject(pub);
			
			RosterGroup subG = getGroupStranger(friend.getUserid());
			Roster sub = new Roster();
			sub.setNickname(owner.getNickname());
			sub.setStatus(ConstantDB.ROSTER_UNHANDLE);
			sub.setUserid(owner.getUserid());
			sub.setGroup(subG);
			sub = (Roster)rosterDao.saveObject(sub);
			messageManager.askMessage(owner.getUserid(), friend.getUserid(), content);
		}catch(Exception e){
			log.error(e);
		}
	}
	/**
	 * 发送好友请求,同时发送消息
	 * 双方都加入各自的默认陌生人组
	 *  ownerid 请求加friendid好友
	 */
	public void ask(Long ownerid, Long friendid, String content) throws Exception{
		try{
			UserInfo owner = userManager.getByUserid(ownerid);
			UserInfo friend = userManager.getByUserid(friendid);
			Roster pub = rosterDao.getRoster(ownerid, friendid);
			Roster sub = null;
			if(pub == null){
				createRoster(owner, friend, content);
			}else{
				sub = rosterDao.getRoster(friendid, ownerid);
				int relation = RosterItem.getStand(pub.getStatus(), sub.getStatus());
				switch (relation){
					case 1:{
						messageManager.askMessage(ownerid, friendid, content);
						break;
					}
					case 2:{
						List<Message> messages = messageManager.getMessages(friendid, ownerid, ConstantDB.MESSAGE_TYPES_ROSTER_REQUEST);
						Long messageid = null;
						if(messages != null && messages.size() > 0){
							messageid = messages.get(0).getMessageid();
						}
						accept(ownerid, friendid, messageid);
						break;
					}
					case 3:{
						pub.setStatus(ConstantDB.ROSTER_REQUEST);
						rosterDao.saveObject(pub);
						messageManager.askMessage(ownerid, friendid, content);
						break;
					}
					case 4:{
						break;
					}
					case 5:{
						break;
					}
					case 6:{
						break;
					}
					case 7:{
						messageManager.askMessage(ownerid, friendid, content);
						break;
					}
					case 8:{
						List<Message> messages = messageManager.getMessages(friendid, ownerid, ConstantDB.MESSAGE_TYPES_ROSTER_REQUEST);
						Long messageid = null;
						if(messages != null && messages.size() > 0){
							messageid = messages.get(0).getMessageid();
						}
						accept(friendid, ownerid, messageid);
						break;
					}
					default:{
						break;
					}
				}
			}
		}catch(Exception e){
			log.error(e);
			throw e;
		}
	}

	/**
	 * 接受请求，同时修改消息状态;
	 * 如果是默认的陌生人组/黑名单组，则移动到默认的好友组(双方)
	 * friendid接受ownerid的请求
	 */
	public void accept(Long friendid, Long ownerid, Long messageid) throws Exception {
		try{
			Roster pub = rosterDao.getRoster(ownerid, friendid);
			Roster sub = rosterDao.getRoster(friendid, ownerid);
			pub.setStatus(ConstantDB.ROSTER_AGREE);
			RosterGroup pubG = pub.getGroup();
			if(pubG.getName().equals(ConstantDB.ROSTER_GROUP_NAME_BLACKLIST) || pubG.getName().equals(ConstantDB.ROSTER_GROUP_NAME_STRANGER)){
				pub.setGroup(getGroupFriend(ownerid));
			}
			sub.setStatus(ConstantDB.ROSTER_AGREE);
			RosterGroup subG = sub.getGroup();
			if(subG.getName().equals(ConstantDB.ROSTER_GROUP_NAME_BLACKLIST) || subG.getName().equals(ConstantDB.ROSTER_GROUP_NAME_STRANGER)){
				sub.setGroup(getGroupFriend(friendid));
			}
			rosterDao.saveObject(pub);
			rosterDao.saveObject(sub);
			
			userManager.addRosterAmount(ownerid);
			userManager.addRosterAmount(friendid);
			
			messageManager.setRead(messageid);
			messageManager.acceptMessage(friendid, ownerid);
		}catch(Exception e){
			log.error(e);
			throw e;
		}
	}
	/**
	 * 拒绝请求，同时修改消息状态; 同时移动到默认的陌生人组(双方)
	 * friendid拒绝ownerid的请求
	 */
	public void reject(Long friendid, Long ownerid, Long messageid) throws Exception {
		try{
			Roster pub = rosterDao.getRoster(ownerid, friendid);
			Roster sub = rosterDao.getRoster(friendid, ownerid);
			pub.setStatus(ConstantDB.ROSTER_REJECT);
			pub.setGroup(getGroupStranger(ownerid));
			sub.setStatus(ConstantDB.ROSTER_REJECT);
			sub.setGroup(getGroupStranger(friendid));
			rosterDao.saveObject(pub);
			rosterDao.saveObject(sub);
			
			messageManager.setRead(messageid);
			messageManager.rejectMessage(friendid, ownerid);
		}catch(Exception e){
			log.error(e);
			throw e;
		}
	}
	/**
	 * 获得UID1对UID2的好友关系，单向
	 */
	public Roster getRoster(Long uid1, Long uid2){
		try {
			return rosterDao.getRoster(uid1, uid2);
		} catch (Exception e) {
			return null;
		}
	}
	/**
	 * 获得puber和suber的好友关系互相
	 */
	public RosterItem getRosterItem(Long puber, Long suber){
		Roster pubR = null, subR = null;
		try {
			pubR = rosterDao.getRoster(puber, suber);
			subR = rosterDao.getRoster(suber, puber);
			if(subR == null || pubR == null){
				throw new Exception();
			}
		} catch (Exception e) {
			return null;
		}
		RosterItem item = new RosterItem(pubR, subR);
		return item;
	}
	/**
	 * 获得用户的所有组
	 */
	public List<RosterGroup> getRosterGroup(Long userid){
		try {
			return rosterGroupDao.getGroups(userid);
		} catch (Exception e) {
			return null;
		}
	}
	/**
	 * 获得用户的组
	 */
	public RosterGroup getRosterGroup(Long userid, String groupName){
		try {
			return rosterGroupDao.getGroup(userid, groupName);
		} catch (Exception e) {
			return null;
		}
	}
	/**
	 * 获得用户除去Forbidden的组
	 */
	public List<RosterGroup> getRosterGroupSelf(Long userid){
		try {
			String extNames = ConstantDB.ROSTER_GROUP_NAME_FORBIDDEN;
			return rosterGroupDao.getRosterGroupLimit(userid, extNames);
		} catch (Exception e) {
			return null;
		}
	}
	/**
	 * 获得用户除去黑名单/陌生人/Forbidden的组
	 */
	public List<RosterGroup> getRosterGroupNormal(Long userid){
		try {
			String extNames = ConstantDB.ROSTER_GROUP_NAME_BLACKLIST + ", "+ConstantDB.ROSTER_GROUP_NAME_STRANGER + ", "+ConstantDB.ROSTER_GROUP_NAME_FORBIDDEN;
			return rosterGroupDao.getRosterGroupLimit(userid, extNames);
		} catch (Exception e) {
			return null;
		}
	}
	
	/**
	 * 任何删除，双方的关系都删除
	 */
	public void removeRoster(Long userid, Long friendid){
		try {
			Roster pubR = rosterDao.getRoster(userid, friendid);
			Roster subR = rosterDao.getRoster(friendid, userid);
			rosterDao.remove(pubR);
			rosterDao.remove(subR);
		} catch (Exception e) {
			log.error(e);
		}
	}
	/**
	 * 用户userid将friendid移动到新组targetGroupid</br>
	 * 需要处理的移动情况包括：</br>
	 * X:表示不处理，V表示处理
	 * <table style="border:1px;"><tr><td>TO\FROM</td><td>Forbidden</td><td>黑名单<br/>(只删除)</td><td>陌生人</td><td>好友</td></tr>
	 * <tr><td>Forbidden</td><td>X</td><td>X</td><td>X</td><td>X</td></tr>
	 * <tr><td>黑名单</td><td>X</td><td>X</td><td>V</td><td>V</td></tr>
	 * <tr><td>陌生人</td><td>X</td><td>X</td><td>X</td><td>V双方陌生人<br/>相当于被移动的人发请求</td></tr><tr>
	 * <td>好友</td><td>X</td><td>X</td><td>V发送方不可移动<br/>接受方可以移动</td><td>V</td></tr>
	 * </table>
	 */
	public void moveGroup(Long userid, Long friendid, Long targetGroupid){
		try {
			Roster pubR = rosterDao.getRoster(userid, friendid);
			Roster subR = rosterDao.getRoster(friendid, userid);
			RosterGroup pubOG = pubR.getGroup();// userid， friendid原来的组
			if(pubOG.getName().equals(ConstantDB.ROSTER_GROUP_NAME_BLACKLIST) || pubOG.getName().equals(ConstantDB.ROSTER_GROUP_NAME_BLACKLIST)){
				//黑名单/被黑名单 组内的好友不能被移动，只能删除
				return ;
			}
			RosterGroup pubNG = (RosterGroup) rosterGroupDao.get(RosterGroup.class, targetGroupid);//新组
			if(pubNG.getName().equals(ConstantDB.ROSTER_GROUP_NAME_BLACKLIST)){//如果userid是将friendid加入黑名单
				pubR.setGroup(pubNG);
				pubR.setStatus(ConstantDB.ROSTER_BLACKLIST);
				rosterDao.saveObject(pubR);
				RosterGroup subG = getGroupForbidden(friendid);
				subR.setGroup(subG);
				subR.setStatus(ConstantDB.ROSTER_FORBIDDEN);
				rosterDao.saveObject(subR);
				return;
			}
			if(pubNG.getName().equals(ConstantDB.ROSTER_GROUP_NAME_FORBIDDEN)){
				//不能将好友移动到Forbidden
				return;
			}
			if(pubOG.getName().equals(ConstantDB.ROSTER_GROUP_NAME_STRANGER)){
				if(pubNG.getName().equals(ConstantDB.ROSTER_GROUP_NAME_STRANGER)){
					//陌生人 -->陌生人
					return ;
				}else{
					//陌生人 -->好友; 发送方不可移动；接受方可以移动
					if(pubR.getStatus().compareTo(ConstantDB.ROSTER_REQUEST) == 0){
						return ;
					}else{
						pubR.setStatus(ConstantDB.ROSTER_AGREE);
						pubR.setGroup(pubNG);
						rosterDao.saveObject(pubR);
						subR.setStatus(ConstantDB.ROSTER_AGREE);
						subR.setGroup(getGroupFriend(friendid));
						rosterDao.saveObject(subR);
						messageManager.acceptMessage(userid, friendid);
					}
					
				}
			}else if(pubOG.getName().equals(ConstantDB.ROSTER_GROUP_NAME_FRIENDS)){
				if(pubNG.getName().equals(ConstantDB.ROSTER_GROUP_NAME_STRANGER)){
					//好友 -->陌生人
					pubR.setStatus(ConstantDB.ROSTER_UNHANDLE);
					pubR.setGroup(pubNG);
					rosterDao.saveObject(pubR);
					subR.setStatus(ConstantDB.ROSTER_REQUEST);
					subR.setGroup(getGroupStranger(friendid));
					rosterDao.saveObject(subR);
				}else if(pubNG.getName().equals(ConstantDB.ROSTER_GROUP_NAME_FRIENDS)){
					//好友 -->好友
					pubR.setGroup(pubNG);
					rosterDao.saveObject(pubR);
				}
			}
		} catch (Exception e) {
			log.error(e);
		}
	}
	
	/**
	 * 用户创建/更新组
	 * 组名不能重复
	 */
	public RosterGroup saveGroup(Long userid, RosterGroup rosterGroup){
		Long groupid = rosterGroup.getGroupid();
		if(groupid == null){
			return createGroup(userid, rosterGroup);
		}else{
			return updateRosterGroup(userid, rosterGroup);
		}
	}
	/**
	 * 用户创建组
	 * 组名不能重复
	 */
	private RosterGroup createGroup(Long userid, RosterGroup rosterGroup){
		RosterGroup group = null;
		try{
			group = rosterGroupDao.getGroup(userid, rosterGroup.getName());
			if(group == null){
				group = rosterGroup;
				if(rosterGroup.getRank() == null){
					group.setRank(ConstantDB.ROSTER_RANK_DEFAULT);
					group.setUserid(userid);
				}
				group = (RosterGroup) rosterGroupDao.saveObject(group);
			}
		}catch(Exception e){
			log.error(e);
		}
		return group;
	}
	/**
	 * 用户更新组名
	 * 组名不能重复
	 * 如果组名已经存在，返回新组名的组
	 */
	private RosterGroup updateRosterGroup(Long userid, RosterGroup rosterGroup){
		try{
			RosterGroup oG = rosterGroupDao.getGroup(userid, rosterGroup.getName());
			if(oG != null){
				if(oG.getGroupid().compareTo(rosterGroup.getGroupid()) == 0){
					oG.setName(rosterGroup.getName());
					oG.setRank(rosterGroup.getRank());
					return (RosterGroup) rosterGroupDao.saveObject(oG);
				}else{
					return oG;
				}
			}else{
				RosterGroup oldG = (RosterGroup) rosterGroupDao.get(RosterGroup.class, rosterGroup.getGroupid());
				oldG .setName(rosterGroup.getName());
				oldG.setRank(rosterGroup.getRank());
				return (RosterGroup) rosterGroupDao.saveObject(oldG);
			}
		}catch(Exception e){
			log.error(e);
			return null;
		}
	}
	/**
	 * 用户删除组；
	 * 不能删除4个默认的组
	 * roster: true同时删除组下所有好友； false只删除组，组下好友被移动到默认好友组
	 */
	public void deleteGroup(Long userid, Long groupid, boolean roster){
		try{
			RosterGroup oldGroup = (RosterGroup) rosterGroupDao.get(RosterGroup.class, groupid);
			Set<Roster> rosters = oldGroup.getGroupUsers();
			if(roster){
				rosterGroupDao.removeAll(rosters);
				rosterGroupDao.remove(oldGroup);
			}else{
				RosterGroup fGroup = getGroupFriend(userid);
				Set<Roster> frosters = fGroup.getGroupUsers();
				frosters.addAll(rosters);
				fGroup.setGroupUsers(frosters);
				rosterGroupDao.saveObject(fGroup);
				oldGroup.setGroupUsers(null);
				rosterGroupDao.remove(oldGroup);
			}
		}catch(Exception e){
			log.error(e);
		}
	}
}